package com.hjh.testdemo.ui.usb.accessory

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.hardware.usb.UsbAccessory
import android.hardware.usb.UsbManager
import android.view.View
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import com.elvishew.xlog.XLog
import com.hjh.core.activity.BaseFragment
import com.hjh.res.R
import com.hjh.testdemo.databinding.FragmentUsbAccessoryBinding
import com.hjh.usb.accessory.communication.UsbAccessoryCommunicator
import com.hjq.toast.Toaster
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

/**
 * @author： hjh
 * @createDate： 2025/6/16 19:06
 * @description：
 * @qq： 3472903821
 * @version: 1.0
 */
class UsbAccessoryDemoFragment : BaseFragment<FragmentUsbAccessoryBinding>() {

    companion object {
        private const val ACTION_USB_PERMISSION = "com.hjh.USB_ACCESSORY_PERMISSION"
    }

    private lateinit var usbManager: UsbManager
    private var communicator: UsbAccessoryCommunicator? = null

    override fun initView() {
        isTopFragment()

        usbManager = requireContext().getSystemService(Context.USB_SERVICE) as UsbManager

        registerReceiver()

        checkAndRequestAccessory()
    }

    override fun initListener() {
        binding.sendButton.setOnClickListener {
            val inputString = binding.inputEdittext.text.toString()
            if (inputString.isNotEmpty()) {
                sendString(inputString)
                binding.inputEdittext.setText("")
            }
        }
        binding.refreshButton.setOnClickListener {
            checkAndRequestAccessory()
        }
    }

    override fun onDestroyView() {
        requireActivity().unregisterReceiver(usbReceiver)
        super.onDestroyView()
    }

    private fun registerReceiver() {
        val filter = IntentFilter(ACTION_USB_PERMISSION)
        ContextCompat.registerReceiver(
            requireActivity(),
            usbReceiver,
            filter,
            ContextCompat.RECEIVER_EXPORTED
        )
    }

    private fun checkAndRequestAccessory() {
        val accessories = usbManager.accessoryList
        if (!accessories.isNullOrEmpty()) {
            XLog.i("全部 accessory: $accessories")
            val accessory = accessories[0]
            XLog.i("准备请求权限的 accessory: $accessory")
            printLineToUI("准备请求权限的 accessory: $accessory")
            if (usbManager.hasPermission(accessory)) {
                Toaster.show("已拥有权限，直接通信")
                startCommunication(accessory)
            } else {
                requestPermission(accessory)
            }
            XLog.i("等待连接 USB Accessory")
            updateStatus("等待连接...")
            Toaster.show("等待连接 USB Accessory")
            printLineToUI("等待连接 USB Accessory")
        } else {
            XLog.e("未发现 USB Accessory")
            updateStatus("未连接")
            Toaster.show("未发现 USB Accessory")
            printLineToUI("未发现 USB Accessory")
        }
    }

    private fun requestPermission(accessory: UsbAccessory) {
        val intent = PendingIntent.getBroadcast(
            requireActivity(), 0,
            Intent(ACTION_USB_PERMISSION),
            PendingIntent.FLAG_IMMUTABLE
        )
        usbManager.requestPermission(accessory, intent)
    }

    @Suppress("Deprecation")
    private val usbReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            printLineToUI(intent?.action.toString())
            if (intent?.action == ACTION_USB_PERMISSION) {
                printLineToUI(intent.extras.toString())
                val accessory = intent.getParcelableExtra<UsbAccessory>(UsbManager.EXTRA_ACCESSORY)
                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    accessory?.let { startCommunication(it) }
                } else {
                    XLog.e("USB 权限被拒绝")
                    Toaster.show("USB 权限被拒绝")
                    printLineToUI("USB 权限被拒绝")
                }
            }
        }
    }

    private fun startCommunication(accessory: UsbAccessory) {
        communicator = object : UsbAccessoryCommunicator(requireContext()) {
            override fun onReceive(payload: ByteArray, length: Int) {
                // XLog.i("onReceive")
                // val received = String(payload, 0, length)
                // printLineToUI(getString(com.hjh.res.R.string.local_receive) + length)
                // sendString("received: $received")
            }

            override fun onConnected() {
                XLog.i("onConnected")
                updateStatus("已连接")
                Toaster.show("已连接")
                printLineToUI("connected")
            }

            override fun onDisconnected() {
                XLog.i("onDisconnected")
                updateStatus("已断开")
                Toaster.show("连接断开")
                printLineToUI("disconnected")
            }

            override fun onError(msg: String) {
                XLog.e("onError: $msg")
                updateStatus("错误")
                Toaster.show("异常： $msg")
                printLineToUI("error: $msg")
            }
        }.apply {
            openAccessory(accessory)
        }
    }

    private fun sendString(string: String) {
        lifecycleScope.launch(Dispatchers.IO) {
            communicator?.let {
                val payload = string.toByteArray()
                it.send(payload)
                printLineToUI(getString(R.string.local_send) + payload.size)
            } ?: run {
                printLineToUI("连接异常，发送失败")
            }
        }
    }

    private fun sendByteArray(data: ByteArray) {
        lifecycleScope.launch(Dispatchers.IO) {
            communicator?.let {
                it.send(data)
                printLineToUI(getString(R.string.local_send) + data.size)
            } ?: run {
                printLineToUI("连接异常，发送失败")
            }
        }
    }

    @SuppressLint("SetTextI18n")
    private fun updateStatus(status: String) {
        lifecycleScope.launch(Dispatchers.Main) {
            binding.statusText.text = getString(R.string.connect_status) + status
        }
    }


    @SuppressLint("SetTextI18n")
    private fun printLineToUI(line: String) {
        lifecycleScope.launch(Dispatchers.Main) {
            // 追加新日志到末尾
            binding.contentText.append("$line\n")

            // 滚动到底部
            binding.accessoryScrollView.post {
                binding.accessoryScrollView.fullScroll(View.FOCUS_DOWN)
            }
        }
    }
}